package com.changgou.seckill.service;

import com.alibaba.fastjson.JSON;
import com.changgou.seckill.config.CustomMessageSender;
import com.changgou.seckill.config.RabbitMQConfig;
import com.changgou.seckill.pojo.SeckillGoods;
import com.changgou.seckill.pojo.SeckillOrder;
import com.changgou.util.IdWorker;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 *
 */
@Service
public class SeckillOrderServiceImpl implements SeckillOrderService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private IdWorker idWorker;

    @Autowired
    private CustomMessageSender customMessageSender;


    @Override
    public Boolean add(String time, Long id, String username) {
        /**
         * 防止用户刷单, 防止用户重复下单
         * 消费者进入到这里, 可以使用下单的商品id+消费者用户名到redis中获取数据
         * 如果获取不到允许下单, 说明用户没有买过这个商品
         * 如果从redis中获取到数据了, 说明用户已经买过这个商品, 不允许重复下单.
         */
        //从redis中获取用户的下单标记
        Object flag = redisTemplate.boundValueOps(username + id).get();
        if (flag != null) {
            throw new RuntimeException("您已经购买过, 不允许重复下单");
        }
        //将用户购买标记存入redis中
        redisTemplate.boundValueOps(username + id).set("1", 2, TimeUnit.HOURS);

        //1.获取秒杀商品数据与库存量数据，如果没有库存则抛出异常
        SeckillGoods seckillGoods = (SeckillGoods) redisTemplate.boundHashOps(time).get(String.valueOf(id));
        if (seckillGoods == null) {
            throw new RuntimeException("商品不存在, 不允许下单!");
        }
        //2.预扣减库存，如果扣完库存量<0，删除商品数据与库存数据, 使用redis中的原子锁
        Object objCount = redisTemplate.opsForValue().get(String.valueOf(id));
        if (objCount == null) {
            throw new RuntimeException("此商品已售罄");
        }
        int stockCount = Integer.parseInt(String.valueOf(objCount));
        if (stockCount <=0) {
            throw new RuntimeException("此商品已售罄");
        }
        //3. 异步redis中的库存, 使用redis中的原子锁
        Long count = redisTemplate.opsForValue().decrement(String.valueOf(id));
        //4. 如果库存量>=0，创建秒杀订单
        if (count < 0) {
            throw new RuntimeException("此商品已售罄, 不允许下单");
        }
        SeckillOrder seckillOrder = new SeckillOrder();
        //秒杀订单id
        seckillOrder.setId(idWorker.nextId());
        //创建时间
        seckillOrder.setCreateTime(new Date());
        //秒杀商品id
        seckillOrder.setSeckillId(id);
        //消费者用户名
        seckillOrder.setUserId(username);
        //价格
        seckillOrder.setMoney(seckillGoods.getCostPrice());
        //订单状态, 0未支付
        seckillOrder.setStatus("0");


        //5. 将秒杀订单对象转换成 json 发送给MQ, 基于mq异步方式完成与mysql数据同步（最终一致性）
        customMessageSender.sendMessage("", RabbitMQConfig.SECKILL_ORDER, JSON.toJSONString(seckillOrder));
        return true;
    }
}
